classdef ALMDataTransformer
    % ALMDataTransformer - ALM数据转换器（静态工具类）
    %
    % 功能：
    % - PR/CR数据在服务器格式和GUI表格格式之间转换
    % - PR/CR数据过滤（按状态、严重性/优先级、搜索关键字）
    % - 数据验证和格式化
    %
    % 设计原则：
    % - 遵循DO-178规则第4条：业务逻辑与GUI分离
    % - 遵循DO-178规则第2条：明确错误处理，不使用fallback机制
    % - 纯静态方法，无状态，便于测试
    %
    % 使用示例：
    %   % 转换PR数据为表格格式
    %   tableData = ALMDataTransformer.convertPRDataToTable(prData);
    %
    %   % 过滤PR表格数据
    %   filters = struct('status', 'Open', 'severity', 'Critical', 'searchText', 'bug');
    %   filteredData = ALMDataTransformer.filterTableData(tableData, filters, 'PR');
    %
    % 作者：DO-178项目开发团队
    % 日期：2025-10-04
    % 版本：1.0
    
    methods (Static)
        
        %% ==================== PR数据转换 ====================
        
        function tableData = convertPRDataToTable(prData)
            % 将ALM服务器返回的PR数据转换为GUI表格格式
            % 输入：prData - PR数据（结构体数组或cell array）
            % 输出：tableData - 表格数据（cell array）
            %       格式：{数据库ID, PR编号, 标题, 状态, 严重性, 创建日期}
            
            tableData = {};
            
            if isempty(prData)
                return;
            end
            
            % 处理结构体数组
            if isstruct(prData)
                for i = 1:length(prData)
                    pr = prData(i);
                    tableData = [tableData; ALMDataTransformer.processPRRecord(pr)]; %#ok<AGROW>
                end
            % 处理cell数组
            elseif iscell(prData)
                for i = 1:length(prData)
                    pr = prData{i};
                    tableData = [tableData; ALMDataTransformer.processPRRecord(pr)]; %#ok<AGROW>
                end
            end
        end
        
        function recordRow = processPRRecord(pr)
            % 处理单条PR记录
            % 输入：pr - PR结构体
            % 输出：recordRow - 单行表格数据（1x6 cell array）
            
            recordRow = {};
            
            if ~isstruct(pr)
                return;
            end
            
            % 提取字段（使用安全的字段访问）
            databaseId = ALMDataTransformer.getFieldValue(pr, 'id', 0);
            issueNumber = ALMDataTransformer.getFieldValue(pr, 'issueNumber', '');
            
            % 处理problemDescription字段（可能是cell或字符串）
            if isfield(pr, 'problemDescription')
                if iscell(pr.problemDescription) && ~isempty(pr.problemDescription)
                    description = pr.problemDescription{1};
                else
                    description = char(pr.problemDescription);
                end
            else
                description = '';
            end
            
            % 状态字段
            status = ALMDataTransformer.getFieldValue(pr, 'approval', '');
            if isempty(status)
                status = ALMDataTransformer.getFieldValue(pr, 'status', 'Unknown');
            end
            
            % 严重性字段
            severity = ALMDataTransformer.getFieldValue(pr, 'severity', '');
            
            % 日期字段（优先使用created_at，其次reportDate）
            if isfield(pr, 'created_at')
                date = pr.created_at;
                % 格式化日期：只取日期部分
                if contains(date, 'T')
                    date = date(1:10);
                end
            elseif isfield(pr, 'reportDate')
                date = pr.reportDate;
            else
                date = '';
            end
            
            % 构造表格行：数据库ID | PR编号 | 标题 | 状态 | 严重性 | 创建日期
            recordRow = {databaseId, issueNumber, description, status, severity, date};
        end
        
        %% ==================== CR数据转换 ====================
        
        function tableData = convertCRDataToTable(crData)
            % 将ALM服务器返回的CR数据转换为GUI表格格式
            % 输入：crData - CR数据（结构体数组或cell array）
            % 输出：tableData - 表格数据（cell array）
            %       格式：{数据库ID, CR编号, 标题, 状态, 优先级, 创建日期}
            
            tableData = {};
            
            if isempty(crData)
                return;
            end
            
            % 处理结构体数组
            if isstruct(crData)
                for i = 1:length(crData)
                    cr = crData(i);
                    tableData = [tableData; ALMDataTransformer.processCRRecord(cr)]; %#ok<AGROW>
                end
            % 处理cell数组
            elseif iscell(crData)
                for i = 1:length(crData)
                    cr = crData{i};
                    tableData = [tableData; ALMDataTransformer.processCRRecord(cr)]; %#ok<AGROW>
                end
            end
        end
        
        function recordRow = processCRRecord(cr)
            % 处理单条CR记录
            % 输入：cr - CR结构体
            % 输出：recordRow - 单行表格数据（1x6 cell array）
            
            recordRow = {};
            
            if ~isstruct(cr)
                return;
            end
            
            % 提取字段
            databaseId = ALMDataTransformer.getFieldValue(cr, 'id', 0);
            ticketNumber = ALMDataTransformer.getFieldValue(cr, 'ticketNumber', '');
            
            % 处理changeDescription字段（可能是cell或字符串）
            if isfield(cr, 'changeDescription')
                if iscell(cr.changeDescription) && ~isempty(cr.changeDescription)
                    description = cr.changeDescription{1};
                else
                    description = char(cr.changeDescription);
                end
            else
                description = '';
            end
            
            % 状态字段
            status = ALMDataTransformer.getFieldValue(cr, 'approval', '');
            if isempty(status)
                status = ALMDataTransformer.getFieldValue(cr, 'status', 'Unknown');
            end
            
            % 优先级字段（CR使用severity作为优先级）
            severity = ALMDataTransformer.getFieldValue(cr, 'severity', '');
            
            % 日期字段
            if isfield(cr, 'created_at')
                date = cr.created_at;
                % 格式化日期
                if contains(date, 'T')
                    date = date(1:10);
                end
            elseif isfield(cr, 'reportDate')
                date = cr.reportDate;
            else
                date = '';
            end
            
            % 构造表格行：数据库ID | CR编号 | 标题 | 状态 | 优先级 | 创建日期
            recordRow = {databaseId, ticketNumber, description, status, severity, date};
        end
        
        %% ==================== 数据过滤 ====================
        
        function filteredData = filterTableData(originalData, filters, dataType)
            % 过滤表格数据
            % 输入：
            %   originalData - 原始表格数据（cell array）
            %   filters - 过滤条件结构体
            %       .status - 状态过滤值（'全部'或中文状态）
            %       .severity - 严重性/优先级过滤值（'全部'或中文级别）
            %       .searchText - 搜索文本（在编号和标题中搜索）
            %   dataType - 数据类型（'PR' 或 'CR'）
            % 输出：filteredData - 过滤后的表格数据
            %
            % 基于规则第2条：支持中文过滤器匹配英文数据
            
            filteredData = originalData;
            
            if isempty(originalData)
                return;
            end
            
            % 验证数据格式：确保至少有6列
            if size(originalData, 2) < 6
                fprintf('❌ %s过滤器错误: 数据列数不足（需要至少6列，实际%d列）\n', dataType, size(originalData, 2));
                return;
            end
            
            % 应用状态过滤（第4列）
            % 支持中文和英文过滤值
            if isfield(filters, 'status') && ~strcmp(filters.status, 'All') && ~strcmp(filters.status, '全部')
                statusMask = strcmp(filteredData(:, 4), filters.status);
                filteredData = filteredData(statusMask, :);
            end
            
            % 应用严重性/优先级过滤（第5列）
            % 支持中文和英文过滤值
            if isfield(filters, 'severity') && ~strcmp(filters.severity, 'All') && ~strcmp(filters.severity, '全部')
                severityMask = strcmp(filteredData(:, 5), filters.severity);
                filteredData = filteredData(severityMask, :);
            end
            
            % 应用搜索文本过滤（在第2列编号和第3列标题中搜索）
            if isfield(filters, 'searchText') && ~isempty(filters.searchText)
                searchText = filters.searchText;
                searchMask = false(size(filteredData, 1), 1);
                
                for i = 1:size(filteredData, 1)
                    % 在编号中搜索（第2列）
                    numberMatch = contains(lower(char(filteredData{i, 2})), lower(searchText));
                    % 在标题中搜索（第3列）
                    titleMatch = contains(lower(char(filteredData{i, 3})), lower(searchText));
                    
                    searchMask(i) = numberMatch || titleMatch;
                end
                
                filteredData = filteredData(searchMask, :);
            end
            
            % 输出过滤结果统计
            fprintf('✅ %s过滤完成: 从 %d 条记录筛选出 %d 条\n', ...
                dataType, size(originalData, 1), size(filteredData, 1));
        end
        
        %% ==================== 数据验证 ====================
        
        function isValid = validateTableData(tableData, dataType)
            % 验证表格数据格式
            % 输入：
            %   tableData - 表格数据（cell array）
            %   dataType - 数据类型（'PR' 或 'CR'）
            % 输出：isValid - 是否有效（true/false）
            
            isValid = false;
            
            if isempty(tableData)
                fprintf('⚠️ %s表格数据为空\n', dataType);
                return;
            end
            
            if ~iscell(tableData)
                fprintf('❌ %s表格数据必须是cell array\n', dataType);
                return;
            end
            
            if size(tableData, 2) ~= 6
                fprintf('❌ %s表格数据必须有6列（实际%d列）\n', dataType, size(tableData, 2));
                return;
            end
            
            isValid = true;
        end
        
        %% ==================== 数据格式化 ====================
        
        function formattedData = formatDateColumn(tableData, columnIndex)
            % 格式化日期列
            % 输入：
            %   tableData - 表格数据
            %   columnIndex - 日期列索引（默认为6）
            % 输出：formattedData - 格式化后的数据
            
            if nargin < 2
                columnIndex = 6;
            end
            
            formattedData = tableData;
            
            if isempty(tableData) || size(tableData, 2) < columnIndex
                return;
            end
            
            for i = 1:size(tableData, 1)
                dateStr = tableData{i, columnIndex};
                if ~isempty(dateStr) && contains(dateStr, 'T')
                    % 移除时间部分，只保留日期
                    formattedData{i, columnIndex} = dateStr(1:10);
                end
            end
        end
        
        function statusText = formatStatus(status)
            % 格式化状态文本（中文映射）
            % 输入：status - 状态字符串（英文）
            % 输出：statusText - 格式化后的状态（中文）
            
            statusMap = containers.Map(...
                {'Open', 'In Progress', 'Resolved', 'Closed', 'Approved', 'Rejected', 'Pending'}, ...
                {'待处理', '处理中', '已解决', '已关闭', '已批准', '已拒绝', '待审批'});
            
            if statusMap.isKey(status)
                statusText = statusMap(status);
            else
                statusText = status;
            end
        end
        
        function severityText = formatSeverity(severity)
            % 格式化严重性文本（中文映射）
            % 输入：severity - 严重性字符串（英文）
            % 输出：severityText - 格式化后的严重性（中文）
            
            severityMap = containers.Map(...
                {'Critical', 'Major', 'Minor', 'Trivial'}, ...
                {'严重', '重要', '一般', '轻微'});
            
            if severityMap.isKey(severity)
                severityText = severityMap(severity);
            else
                severityText = severity;
            end
        end
        
        %% ==================== 工具方法 ====================
        
        function value = getFieldValue(structData, fieldName, defaultValue)
            % 安全地获取结构体字段值
            % 输入：
            %   structData - 结构体
            %   fieldName - 字段名
            %   defaultValue - 默认值
            % 输出：value - 字段值或默认值
            
            if isfield(structData, fieldName) && ~isempty(structData.(fieldName))
                value = structData.(fieldName);
            else
                value = defaultValue;
            end
        end
        
        function summary = generateTableSummary(tableData, dataType)
            % 生成表格数据统计摘要
            % 输入：
            %   tableData - 表格数据
            %   dataType - 数据类型（'PR' 或 'CR'）
            % 输出：summary - 统计摘要结构体
            
            summary = struct();
            summary.dataType = dataType;
            summary.totalCount = size(tableData, 1);
            
            if summary.totalCount == 0
                return;
            end
            
            % 统计状态分布（第4列）
            statusColumn = tableData(:, 4);
            uniqueStatuses = unique(statusColumn);
            summary.statusDistribution = struct();
            for i = 1:length(uniqueStatuses)
                status = uniqueStatuses{i};
                count = sum(strcmp(statusColumn, status));
                summary.statusDistribution.(matlab.lang.makeValidName(status)) = count;
            end
            
            % 统计严重性分布（第5列）
            severityColumn = tableData(:, 5);
            uniqueSeverities = unique(severityColumn);
            summary.severityDistribution = struct();
            for i = 1:length(uniqueSeverities)
                severity = uniqueSeverities{i};
                count = sum(strcmp(severityColumn, severity));
                summary.severityDistribution.(matlab.lang.makeValidName(severity)) = count;
            end
            
            fprintf('📊 %s数据统计: 共 %d 条记录\n', dataType, summary.totalCount);
        end
        
    end
end



